const PENDDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  constructor(executor) {
    //初始状态
    this.status = PENDDING;
    //存放成功的值
    this.value = undefined;
    //存放失败的原因
    this.reason = undefined;
    //成功存放成功的回调
    this.onResolvedCallbacks = [];
    //失败存放失败的回调
    this.onRejectedCallbacks = [];
    const resolve = (data) => {
      //状态是pending才能修改状态
      if (this.status === PENDDING) {
        this.status = FULFILLED;
        this.value = data;
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      //状态是pending才能修改状态
      if (this.status === PENDDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (error) {
      reject(error);
    }
  }
  resolvedPromise(promise, result, resolve, reject) {
    if (promise === result)
      reject(new TypeError("Chaining cycle detected for promise"));
    // 在 JavaScript 中，函数也是一种对象，因此也可以具有 then 方法。如果 result 是一个函数并且具有 then 方法，那么就会按照 Promise/A+ 规范来处理它，调用它的 then 方法，并根据其返回值来决定当前 Promise 的状态和值。
    if (
      (result && typeof result === "object") ||
      typeof result === "function"
    ) {
      //处理嵌套的Promise对象思路是使用递归
      //如果传入的 result 是一个对象或者一个函数的话，令 then = result.then。
      //然后判断 then 是否是一个函数，如果是就说明 result 是一个 promise 对象，那就调用 then，并且    把 result 作为 this，然后在成功回调中继续调用 resolvedPromise 并且把拿到的值作为新的 result 传入，其他不变。
      //如果 then 不是一个函数，那就说明 result 是一个函数或者是一个普通对象，那就直接 resolve。
      //如果传入的 result 不是一个对象且不是一个函数，就直接 resolve 即可，同时这也是该递归的最终状态。
      //为了保证成功和失败只能调用其中一个，声明变量 called 来作为标记。
      //使用 try...catch 来进行异常处理。
      let called;
      try {
        let then = result.then;
        if (typeof then === "function") {
          then.call(
            result,
            (value) => {
              if (called) return;
              called = true;
              this.resolvedPromise(promise, value, resolve, reject);
            },
            (reason) => {
              if (called) return;
              called = true;
              reject(reason);
            }
          );
        } else {
          if (called) return;
          called = true;
          resolve(result);
        }
      } catch (error) {
        if (called) return;
        called = true;
        reject(error);
      }
    } else {
      resolve(result);
    }
  }
  then(onFulfilled, onRejected) {
    //处理then的参数，如果参数不是函数，那么忽略它
    if (typeof onFulfilled !== "function")
      onFulfilled = (value) => {
        return value;
      };
    if (typeof onRejected !== "function")
      onRejected = (reason) => {
        throw reason;
      };
    let promise = new MyPromise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //使用queueMicrotask处理then方法的异步执行
        queueMicrotask(() => {
          try {
            this.resolvedPromise(
              promise,
              onFulfilled(this.value),
              resolve,
              reject
            );
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.status === REJECTED) {
        queueMicrotask(() => {
          try {
            this.resolvedPromise(
              promise,
              onRejected(this.reason),
              resolve,
              reject
            );
          } catch (error) {
            reject(error);
          }
        });
      }
      if (this.status === PENDDING) {
        this.onResolvedCallbacks.push(() =>
          queueMicrotask(() => {
            try {
              this.resolvedPromise(
                promise,
                onFulfilled(this.value),
                resolve,
                reject
              );
            } catch (error) {
              reject(error);
            }
          })
        );
        this.onRejectedCallbacks.push(() =>
          queueMicrotask(() => {
            try {
              this.resolvedPromise(
                promise,
                onRejected(this.reason),
                resolve,
                reject
              );
            } catch (error) {
              reject(error);
            }
          })
        );
      }
    });
    return promise;
  }
  catch(err) {
    return this.then(null, err);
  }
  static resolve(value) {
    let promise = new MyPromise((resolve, reject) => {
      queueMicrotask(() => {
        promise.resolvedPromise(promise, value, resolve, reject);
      });
    });
    return promise;
  }
  static reject(reason) {
    return new MyPromise((resolve, reject) => {
      reject(reason);
    });
  }
  static all(promises) {
    return new MyPromise((resolve, reject) => {
      let results = [];
      let count = 0;
      let index = 0;
      for (let promise of promises) {
        let resultIndex = index;
        index += 1;
        MyPromise.resolve(promise).then(
          (e) => {
            count += 1;
            results[resultIndex] = e;
            if (count === index) resolve(results);
          },
          (reason) => {
            reject(reason);
          }
        );
      }
      if (index === 0) resolve(results);
    });
  }
  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise) => {
        MyPromise.resolve(promise).then(resolve, reject);
      });
    });
  }
  static any(values) {
    // 只要任意一个Promise兑现为fulfilled，P的状态为fulfilled
    // 当所有的Promise都被兑现为rejected时，P的状态为rejected

    return new MyPromise((resolve, reject) => {
      const results = [];
      let count = 0;
      let index = 0;
      for (const value of values) {
        let resultIndex = index;
        index++;
        MyPromise.resolve(value).then(
          (value) => {
            resolve(value);
          },
          (reason) => {
            results[resultIndex] = reason;
            count++;
            if (count === index) {
              reject(results);
            }
          }
        );
      }
    });
  }
  static allSettled(values) {
    return new MyPromise((resolve) => {
      const results = [];
      let count = 0;
      let index = 0;
      for (const value of values) {
        let resultIndex = index;
        index++;
        MyPromise.resolve(value).then(
          (value) => {
            results[resultIndex] = {
              status: "fulfilled",
              value,
            };
            count++;
            if (count === index) {
              resolve(results);
            }
          },
          (reason) => {
            results[resultIndex] = {
              status: "rejected",
              reason,
            };
            count++;
            if (count === index) {
              resolve(results);
            }
          }
        );
      }
      if (index === 0) {
        resolve(results);
      }
    });
  }
}
//以下是用于测试的代码
MyPromise.defer = MyPromise.deferred = function () {
  let dfd = {};
  dfd.promise = new MyPromise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};
module.exports = MyPromise;
